//-------------------------------------------------------------------------------------
// <copyright file="UndeployResource.cs" company="Achmea">
// Copyright (c) Microsoft Corporation.  All rights reserved.
// THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY 
// KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
// </copyright>
// <summary>
//      Undeploy an resource from BizTalk.
// </summary>  
//-------------------------------------------------------------------------------------
namespace Microsoft.Sdc.Tasks.BizTalk2006.Assembly
{
    #region Using directives

    using System;
    using System.Globalization;
    using BizTalk.ApplicationDeployment;
    using Microsoft.Build.Framework;
    using System.IO;

    #endregion

    /// <summary>
    /// UnDeploys a resource from BizTalk.
    /// </summary>
    /// <remarks>
    /// <code>
    /// <![CDATA[<BizTalk2006.Assembly.UndeployResource 
    ///     Application="App" 
    ///     ResourceType="System.BizTalk:BizTalkAssembly" 
    ///     AssemblyPath="C:\Build\Output\MyAssembly.dll" 
    ///     Overwrite="True" 
    ///     Destination="C:\Output" 
    ///     Options="AddOnGac,AddOnMsi" 
    ///     Properties="TargetEnvironment='Development'" 
    ///     Server="." 
    ///     Database="BizTalkMgmtDb" 
    ///     Username="sa" 
    ///     Password="foo" />
    /// ]]>
    /// </code>
    /// <para>where:</para>
    /// <para><i>assemblyPath (Required)</i></para>
    /// <para>
    /// The path to the assembly. All neseccary information will be found to undeploy the artifact.
    /// </para>
    /// <para><i>ResourceType (Required)</i></para>
    /// <para>
    /// The ResourceType of the resource.
    /// <list type="string">
    ///     <item>System.BizTalk:Assembly</item>
    ///     <item>System.BizTalk:Bam</item>
    ///     <item>System.BizTalk:Bas</item> 
    ///     <item>System.BizTalk:BizTalkAssembly</item> 
    ///     <item>System.BizTalk:BizTalkBinding</item>
    ///     <item>System.BizTalk:Certificate</item>
    ///     <item>System.BizTalk:Com</item> 
    ///     <item>System.BizTalk:File</item> 
    ///     <item>System.BizTalk:PostProcessingScript</item> 
    ///     <item>System.BizTalk:PreProcessingScript</item> 
    ///     <item>System.BizTalk:Rules</item> 
    ///     <item>System.BizTalk:WebDirectory</item> 
    /// </list>
    /// </para>
    /// <para><i>Application</i></para>
    /// <para>
    /// The BizTalk application to where the resource should be deployed.
    /// </para>
    /// <para><i>SimpleName</i></para>
    /// <para>
    /// The name of the resource.
    /// </para>
    /// <para><i>Culture</i></para>
    /// <para>
    /// The culture of the resource.
    /// </para>
    /// <para><i>Version</i></para>
    /// <para>
    /// The Version when a ruleset is deployed. Only use when the ResourceType is Rules
    /// </para>
    /// <para><i>server</i></para>
    /// <para>
    /// The logical name of the server hosting the BizTalk management database. If neither this nor the
    /// database name are specified then the installation will default to the local installation.
    /// </para>
    /// <para><i>database</i></para>
    /// <para>
    /// The name of the BizTalk management database. If neither this nor the server name are specified 
    /// then the installation will default to the local installation.
    /// </para>
    /// <b>When the following Types are used. The AssemblyPath should have the BizTalk Luid instead of the AssemblyPath.
    /// <list type="string">
    ///   <item>System.BizTalk:Bas</item> 
    ///   <item>System.BizTalk:Certificate</item>
    ///   <item>System.BizTalk:Rules</item> 
    ///   <item>System.BizTalk:WebDirectory</item> 
    /// </list>
    /// </b>
    /// </remarks>
    /// <example>
    /// <code><![CDATA[
    /// <Project>
    ///     <Target Name="Test" >
    ///         <BizTalk2006.Assembly.Addon.Deploy
    ///             Application="App"
    ///             ResourceType="System.BizTalk:BizTalkAssembly"
    ///             AssemblyPath="C:\Build\Output\MyAssembly.dll" 
    ///             Overwrite="True"
    ///             Destination="C:\Output"
    ///             Options="AddOnGac,AddOnMsi"
    ///             Properties="TargetEnvironment='Development'"
    ///             Server="." 
    ///             Database="BizTalkMgmtDb" 
    ///             Username="sa" 
    ///             Password="foo" />
    ///     </Target>
    /// </Project>
    /// ]]></code>
    /// </example>
    public class UndeployResource : BizTalk2004.BizTalk2004TaskBase
    {
        #region Member Variables

        private string application;
        private string assemblyPath;
        private string resourceType;
        private string culture;
        private string publicKeyToken;
        private string simpleName;
        private Version version;

        #endregion

        #region Properties

        /// <summary>
        /// Gets or sets the application.
        /// </summary>
        /// <value>The application.</value>
        public string Application
        {
            get { return this.application; }
            set { this.application = value; }
        }

        /// <summary>
        /// Gets or sets the resourcetype
        /// </summary>
        /// <value>The resource type. 
        /// The following resource types can be filled
        /// <list type="string">
        ///     <item>System.BizTalk:Assembly</item>
        ///     <item>System.BizTalk:Bam</item>
        ///     <item>System.BizTalk:Bas</item> 
        ///     <item>System.BizTalk:BizTalkAssembly</item> 
        ///     <item>System.BizTalk:BizTalkBinding</item>
        ///     <item>System.BizTalk:Certificate</item>
        ///     <item>System.BizTalk:Com</item> 
        ///     <item>System.BizTalk:File</item> 
        ///     <item>System.BizTalk:PostProcessingScript</item> 
        ///     <item>System.BizTalk:PreProcessingScript</item> 
        ///     <item>System.BizTalk:Rules</item> 
        ///     <item>System.BizTalk:WebDirectory</item> 
        /// </list>
        /// </value>
        [Required]
        public string ResourceType
        {
            get { return this.resourceType; }
            set { this.resourceType = value; }
        }

        /// <summary>
        /// Gets or sets the path to the assembly to undeploy.
        /// </summary>
        /// <value>
        /// The path to the assembly to undeploy.
        /// </value>
        public string AssemblyPath
        {
            get { return this.assemblyPath; }
            set { this.assemblyPath = value; }
        }

        /// <summary>
        /// Gets or sets the culture supported by the assembly.
        /// </summary>
        /// <value>
        /// The culture supported by the assembly.
        /// </value>
        public string Culture
        {
            get { return this.culture; }
            set { this.culture = value; }
        }

        /// <summary>
        /// Gets or sets the public key token of the assembly.
        /// </summary>
        /// <value>
        /// The public key token of the assembly.
        /// </value>
        public string PublicKeyToken
        {
            get { return this.publicKeyToken; }
            set { this.publicKeyToken = value; }
        }

        /// <summary>
        /// Gets or sets the simple name of the assembly.
        /// </summary>
        /// <value>
        /// The simple name of the assembly.
        /// </value>
        public string SimpleName
        {
            get { return this.simpleName; }
            set { this.simpleName = value; }
        }

        /// <summary>
        /// Gets or sets the version of the assembly.
        /// </summary>
        /// <value>
        /// The version of the assembly.
        /// </value>
        public string Version
        {
            get { return (this.version == null) ? string.Empty : this.version.ToString(); }
            set { this.version = string.IsNullOrEmpty(value) ? null : new Version(value); }
        }

        #endregion

        #region Methods

        /// <summary>
        /// Executes the task.
        /// </summary>
        protected override void InternalExecute()
        {
                BizTalk2004.Configuration.BizTalkInstallation installation = this.GetInstallation();
                string resourceType = this.ResourceType;
                resourceType = SdmParser.GetInstance().TransformResourceType(resourceType);

                using (Group group = new Group())
                {
                    group.DBServer = installation.Server;
                    group.DBName = installation.Database;

                    try
                    {
                        Application app = group.Applications[this.Application];
                        if (app != null)
                        {
                            app.UILevel = 2;

                            string name;
                            switch (resourceType)
                            {
                                case "System.BizTalk:Assembly":
                                case "System.BizTalk:BizTalkAssembly":
                                    System.Reflection.Assembly ass = System.Reflection.Assembly.ReflectionOnlyLoadFrom(this.AssemblyPath);
                                    name = ass.FullName;
                                    Log.LogMessage(string.Format(CultureInfo.InvariantCulture, "Checking for resource: {0} ({1}) of Application {2}", name, this.ResourceType, this.Application));
                                    break;
                                case "System.BizTalk:BizTalkBinding":
                                case "System.BizTalk:Com":
                                case "System.BizTalk:File":
                                case "System.BizTalk:PostProcessingScript":
                                case "System.BizTalk:PreProcessingScript":
                                case "System.BizTalk:Bam":
                                    FileInfo info = new FileInfo(this.AssemblyPath);
                                    name = info.Name;
                                    Log.LogMessage(string.Format(CultureInfo.InvariantCulture, "Checking for resource: {0} ({1}) of Application {2}", name, this.ResourceType, this.Application));
                                    break;
                                case "System.BizTalk:WebDirectory":
                                case "System.BizTalk:Bas":
                                case "System.BizTalk:Certificate":
                                case "System.BizTalk:Rules":
                                    // When these types are used, the assemblypath should be equal to the BizTalk Luid.
                                    name = this.AssemblyPath;
                                    break;
                                default:
                                    throw new Exception("Invalid ResourceType");
                            }

                            Log.LogMessage(string.Format(CultureInfo.InvariantCulture, "Removing Resource {0} ({1}) will be removed from application {2}", this.AssemblyPath, this.ResourceType, this.Application));
                            app.ResourceCollection.Remove(resourceType, name);
                        }
                        else
                        {
                            Log.LogError(string.Format(CultureInfo.InvariantCulture, "Application not found: {0}", this.Application));
                            return;
                        }
                    }
                    catch (Exception ex)
                    {
                        Log.LogError(string.Format(CultureInfo.InvariantCulture, "Undeploy Assembly failure: {0}", ex));
                        group.Abort();
                        throw;
                    }
                }
        }

        #endregion
    }
}

